﻿#include "HumanWizard.h"
#include "../../../Shared/Enums.h"
#include "../../../Shared/Functions/Functions.h"
#include "../../../Shared/ServerPackets.h"
#include "../../../Shared/Data/Stat.h"
#include "../DelayedAction.h"
#include "../PlayerObject.h"

using namespace Server::MirDatabase;
namespace S = ServerPackets;

namespace Server::MirObjects::Monsters
{

    HumanWizard::HumanWizard(MonsterInfo *info) : MonsterObject(info)
    {
        setDirection(MirDirection::Down);
        Summoned = true;
    }

    bool HumanWizard::InAttackRange()
    {
        return getCurrentMap() == getTarget()->getCurrentMap() && Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), AttackRange);
    }

    void HumanWizard::Attack()
    {
        if (!getTarget()->IsAttackTarget(this))
        {
            setTarget(nullptr);
            return;
        }

        ShockTime = 0;

        setDirection(Functions::DirectionFromPoint(getCurrentLocation(), getTarget()->getCurrentLocation()));
        S::ObjectMagic *tempVar = new S::ObjectMagic();
        tempVar->ObjectID = ObjectID;
        tempVar->Direction = getDirection();
        tempVar->Location = getCurrentLocation();
        tempVar->Spell = Spell::ThunderBolt;
        tempVar->TargetID = getTarget()->ObjectID;
        tempVar->Target = getTarget()->getCurrentLocation();
        tempVar->Cast = true;
        tempVar->Level = 3;
        Broadcast(tempVar);

        ActionTime = getEnvir()->getTime() + 300;
        AttackTime = getEnvir()->getTime() + AttackSpeed;

        int damage = GetAttackPower(Stats[Stat::MinMC], Stats[Stat::MaxMC]);
        if (damage == 0)
        {
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        DelayedAction *action = new DelayedAction(DelayedType::Damage, getEnvir()->getTime() + 500, {getTarget(), damage, DefenceType::MAC});
        ActionList.push_back(action);

//C# TO C++ CONVERTER TODO TASK: A 'delete action' statement was not added since action was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void HumanWizard::ProcessAI()
    {
        MonsterObject::ProcessAI();

        if (Master != nullptr && dynamic_cast<PlayerObject*>(Master) != nullptr && getEnvir()->getTime() > DecreaseMPTime)
        {
            DecreaseMPTime = getEnvir()->getTime() + 1000;
            if (!Master->Dead)
            {
                (static_cast<PlayerObject*>(Master))->ChangeMP(-10);
            }

            if ((static_cast<PlayerObject*>(Master))->getMP() <= 0)
            {
                Die();
            }
        }
    }

    void HumanWizard::ProcessTarget()
    {
        if (getTarget() == nullptr || !getCanAttack())
        {
            return;
        }

        if (Master != nullptr)
        {
            MoveTo(Master->getCurrentLocation());
        }

        if (InAttackRange() && (Master != nullptr || getEnvir()->getTime() < FearTime))
        {
            Attack();
            return;
        }

        FearTime = getEnvir()->getTime() + 5000;

        if (getEnvir()->getTime() < ShockTime)
        {
            setTarget(nullptr);
            return;
        }

        int dist = Functions::MaxDistance(getCurrentLocation(), getTarget()->getCurrentLocation());

        if (dist < AttackRange)
        {
            MirDirection dir = Functions::DirectionFromPoint(getTarget()->getCurrentLocation(), getCurrentLocation());

            if (Walk(dir))
            {
                return;
            }

            switch (getEnvir()->Random->Next(2)) //No favour
            {
                case 0:
                    for (int i = 0; i < 7; i++)
                    {
                        dir = Functions::NextDir(dir);

                        if (Walk(dir))
                        {
                            return;
                        }
                    }
                    break;
                default:
                    for (int i = 0; i < 7; i++)
                    {
                        dir = Functions::PreviousDir(dir);

                        if (Walk(dir))
                        {
                            return;
                        }
                    }
                    break;
            }
        }
    }

    void HumanWizard::Spawned()
    {
        MonsterObject::Spawned();
        Summoned = false;
    }

    void HumanWizard::ChangeHP(int amount)
    {
        if (Master != nullptr && dynamic_cast<PlayerObject*>(Master) != nullptr)
        {
            (static_cast<PlayerObject*>(Master))->ChangeMP(amount);
            return;
        }
        MonsterObject::ChangeHP(amount);
    }

    void HumanWizard::Die()
    {
        if (Dead)
        {
            return;
        }

        HP = 0;
        Dead = true;

        //DeadTime = Envir.Time + DeadDelay;
        DeadTime = 0;

        S::ObjectDied *tempVar = new S::ObjectDied();
        tempVar->ObjectID = ObjectID;
        tempVar->Direction = getDirection();
        tempVar->Location = getCurrentLocation();
        tempVar->Type = static_cast<unsigned char>(Master != nullptr ? 1 : 0);
        Broadcast(tempVar);

        if (EXPOwner != nullptr && Master == nullptr && EXPOwner->getRace() == ObjectType::Player)
        {
            EXPOwner->WinExp(getExperience());
        }

        if (Respawn != nullptr)
        {
            Respawn->Count--;
        }

        if (Master == nullptr)
        {
            Drop();
        }

        PoisonList.clear();
        getEnvir()->MonsterCount--;
        getCurrentMap()->MonsterCount--;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    Packet *HumanWizard::GetInfo()
    {
        PlayerObject *master = nullptr;
        short weapon = -1;
        short armour = 0;
        unsigned char wing = 0;
        if (Master != nullptr && dynamic_cast<PlayerObject*>(Master) != nullptr)
        {
            master = static_cast<PlayerObject*>(Master);
        }
        if (master != nullptr)
        {
            weapon = master->Looks_Weapon;
            armour = master->Looks_Armour;
            wing = master->Looks_Wings;
        }
        S::ObjectPlayer *tempVar = new S::ObjectPlayer();
        tempVar->ObjectID = ObjectID;
        tempVar->Name = master != nullptr ? master->getName() : getName();
        tempVar->NameColour = NameColour;
        tempVar->Class = master != nullptr ? master->getClass() : MirClass::Wizard;
        tempVar->Gender = master != nullptr ? master->getGender() : MirGender::Male;
        tempVar->Location = getCurrentLocation();
        tempVar->Direction = getDirection();
        tempVar->Hair = master != nullptr ? master->getHair() : static_cast<unsigned char>(0);
        tempVar->Weapon = weapon;
        tempVar->Armour = armour;
        tempVar->Light = master != nullptr ? master->Light : Light;
        tempVar->Poison = CurrentPoison;
        tempVar->Dead = Dead;
        tempVar->Hidden = getHidden();
        tempVar->Effect = SpellEffect::None;
        tempVar->WingEffect = wing;
        tempVar->Extra = Summoned;
        tempVar->TransformType = -1;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was used in a 'return' or 'throw' statement.
        return tempVar;
    }
}
